﻿using System;
using System.Collections.Generic;
using System.Text;
using WebApi.Service.Dto;
using WebApi.Repository;
using System.Linq;
using WebApi.Repository.Entity;
using WebApi.Service.tools;
using WebApi.Service.Other;

namespace WebApi.Service.Impl
{
    public class ProductService : IProductService
    {
        private readonly CommodityDbContext commodityDbContext;
        public ProductService(CommodityDbContext commodityDbContext)
        {
            this.commodityDbContext = commodityDbContext;
        }
        /// <summary>
        /// 创建商品
        /// </summary>
        /// <param name="product">前端传入的数据</param>
        /// <returns></returns>
        public ResponseResult<bool> CreateProduct(CreateProductDto product)
        {
            //若商品编号为空或null，返回false
            if (String.IsNullOrEmpty(product.ItemNumber))
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品编号不能为空"
                };
            //若商品编号长度大于100，返回false
            if (product.ItemNumber.Length > 100)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品编号长度不能大于100"
                };
            //若商品名称为空或null，返回false
            if (String.IsNullOrEmpty(product.Name))
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品名称不能为空"
                };
            //若商品名称长度大于100，返回false
            if (product.Name.Length > 100)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品名称长度不能超过100"
                };
            //商品描述非必填，若商品描述长度大于2000，返回false
            if (product.Description == null) product.Description = "";
            if (product.Description.Length > 2000)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品描述长度不能大于2000"
                };
            //商品标签非必填，若商品标签数大于5，返回false
            if (product.TagsId == null) product.TagsId = new List<long>();
            else if (product.TagsId.Count > 5)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品标签数不能大于5"
                };
            //价格必填，将价格保留两位小数
            if (product.Price <= 0)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = product.Price == 0 ? "商品价格不能为空" : "商品价格不能为负数"
                };
            product.Price = Math.Round(product.Price, 2);
            //若填入的标签重复，返回false
            for (int i = 0; i < product.TagsId.Count; i++)
            {
                for (int j = i + 1; j < product.TagsId.Count; j++)
                {
                    if (product.TagsId[i] == product.TagsId[j])
                        return new ResponseResult<bool>()
                        {
                            State = 2,
                            Data = false,
                            Message = "商品标签不能重复输入"
                        };
                }
            }
            //若商品编号已存在，返回false
            var productEntity = commodityDbContext.Products.Where(o => o.ItemNumber == product.ItemNumber).FirstOrDefault();
            if (productEntity != null)
            {
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品编号已存在"
                };
            }
            //若填入的标签不存在或已删除，返回false，同时保存对应插入标签的id
            List<long> tagIds = new List<long>();
            bool b = true;
            long falseId=0;
            foreach (long tagId in product.TagsId)
            {
                var tag = commodityDbContext.Tags.Where(o => o.Id == tagId).FirstOrDefault();
                if (tag == null || tag.IsDeleted == true)
                {
                    b = false;
                    falseId = tagId;
                    break;
                }
                else
                {
                    tagIds.Add(tag.Id);
                }
            }
            if (!b) return new ResponseResult<bool>()
            {
                State = 2,
                Data = false,
                Message = $"填入的id为{falseId}的标签不存在"
            };
            using (var transaction = commodityDbContext.Database.BeginTransaction())
                try
                {
                    //新增商品
                    var newProduct = new ProductEntity
                    {
                        ItemNumber = product.ItemNumber,
                        Name = product.Name,
                        Price = product.Price,
                        Description = product.Description,
                        State = 0
                    };
                    commodityDbContext.Products.Add(newProduct);
                    var changes = commodityDbContext.SaveChanges();
                    //新增失败，返回false
                    if (changes == 0) throw new Exception("新增失败");
                    //增加对应的标签关联
                    foreach (long id in tagIds)
                    {
                        commodityDbContext.ProductTags.Add(new ProductTag
                        {
                            ProductId = newProduct.Id,
                            TagId = id
                        });
                    }
                    if (tagIds.Count != 0 && commodityDbContext.SaveChanges() == 0) throw new Exception("标签关联插入失败");
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    return new ResponseResult<bool>()
                    {
                        State = 3,
                        Data = false,
                        Message = ex.Message
                    };
                }
            return new ResponseResult<bool>()
            {
                State = 1,
                Data = true,
                Message = "新增成功"
            };

        }

        public ResponseResult<bool> DeleteProduct(List<long>productsId)
        {
            var products = commodityDbContext.Products.Where(o => productsId.Contains(o.Id)).ToList();
            if(products.Count!=productsId.Count)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "删除的项不存在"
                };
            foreach (var productEntity in products)
            {       
                //已上架的商品不能删除，state=1代表已上架
                if (productEntity.State == 1)
                    return new ResponseResult<bool>()
                    {
                        State = 2,
                        Data = false,
                        Message = "已上架的商品不能删除"
                    };
                using (var transaction = commodityDbContext.Database.BeginTransaction())
                    try
                    {
                        //删除对应的商品
                        commodityDbContext.Products.Remove(productEntity);
                        var changeProduct = commodityDbContext.SaveChanges();
                        if (changeProduct == 0) throw new Exception("商品删除失败");
                        //删除关联表中与该商品对应的关联信息
                        var productTags = commodityDbContext.ProductTags.Where(o => o.ProductId == productEntity.Id).ToList();
                        foreach (ProductTag productTag in productTags)
                        {
                            commodityDbContext.ProductTags.Remove(productTag);
                        }
                        commodityDbContext.SaveChanges();
                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        return new ResponseResult<bool>()
                        {
                            State = 3,
                            Data = false,
                            Message = ex.Message
                        };
                    }
            }
            return new ResponseResult<bool>()
            {
                State = 1,
                Data = true,
                Message = "商品删除成功"
            };
        }
        public ResponseResult<bool> UpdateProduct(UpdateProductDto product)
        {
            //商品名称必填
            if (String.IsNullOrEmpty(product.Name))
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品名称不能为空"
                };
            //名称长度不能超过100
            if (product.Name.Length > 100)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品名称长度不能超过100"
                };
            //商品描述非必填，长度小于2000
            if (product.Description == null) product.Description = "";
            else if (product.Description.Length > 2000)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品描述长度不能超过2000"
                };
            //商品价格必填，保留两位小数
            if (product.Price <= 0)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = product.Price==0?"商品价格不能为空":"商品价格不能为负数"
                };
            product.Price = Math.Round(product.Price, 2);
            //商品标签非必填，最多使用5个标签
            if (product.TagsId == null) product.TagsId = new List<long>();
            if (product.TagsId.Count > 5)
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "商品标签数不能超过5"
                };
            //若填入的标签重复，返回false
            for (int i = 0; i < product.TagsId.Count; i++)
            {
                for (int j = i + 1; j < product.TagsId.Count; j++)
                {
                    if (product.TagsId[i] == product.TagsId[j])
                        return new ResponseResult<bool>()
                        {
                            State = 2,
                            Data = false,
                            Message = "填入的标签不能重复"
                        };
                }
            }
            //根据id获取相应的商品信息
            var productEntity = commodityDbContext.Products.Where(o => o.Id == product.Id).FirstOrDefault();
            if (productEntity == null)
            {
                return new ResponseResult<bool>()
                {
                    State = 3,
                    Data = false,
                    Message = "修改的对应商品不存在"
                };
            }
            //若填入的标签重复，返回false
            for(int i=0;i<product.TagsId.Count;i++)
                for(int j=i+1;j<product.TagsId.Count;j++)
                    if(product.TagsId[i]==product.TagsId[j])
                return new ResponseResult<bool>()
                {
                    State = 2,
                    Data = false,
                    Message = "标签不能重复填入"
                };
            //若填入的标签不存在或已删除，返回false，同时获取相应的标签id
            List<long> newTagsId = new List<long>();
            bool b = true;
            foreach (long tagId in product.TagsId)
            {
                var tag = commodityDbContext.Tags.Where(o => o.Id==tagId).FirstOrDefault();
                if (tag == null || tag.IsDeleted == true)
                {
                    b = false;
                    break;
                }
                else
                {
                    newTagsId.Add(tag.Id);
                }
            }
            if (!b) return new ResponseResult<bool>()
            {
                State = 2,
                Data = false,
                Message = "填入的标签不存在"
            };
            //更新商品信息、删除原有关联、新增关联
            using (var transaction = commodityDbContext.Database.BeginTransaction())
                try
                {
                    //修改相关的商品信息
                    productEntity.Name = product.Name;
                    productEntity.Price = product.Price;
                    productEntity.Description = product.Description;
                    var changes = commodityDbContext.SaveChanges();
                    //删除原有的商品与标签之间的关联
                    var productTags = commodityDbContext.ProductTags.Where(o => o.ProductId == productEntity.Id).ToList();
                    foreach (ProductTag productTag in productTags)
                    {
                        commodityDbContext.ProductTags.Remove(productTag);
                    }
                    if (productTags.Count != 0 && commodityDbContext.SaveChanges() == 0) throw new Exception("删除原有关联失败");
                    //增加新的商品与标签之间的关联
                    foreach (long id in newTagsId)
                    {
                        commodityDbContext.ProductTags.Add(new ProductTag
                        {
                            ProductId = productEntity.Id,
                            TagId = id
                        });
                    }
                    if (newTagsId.Count != 0 && commodityDbContext.SaveChanges() == 0) throw new Exception("标签关联插入失败");
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return new ResponseResult<bool>()
                    {
                        State = 3,
                        Data = false,
                        Message = ex.Message
                    };
                }
            return new ResponseResult<bool>()
            {
                State = 1,
                Data = true,
                Message = "修改成功"
            };
        }

        /// <summary>
        /// GetProducts筛选函数的辅助函数，返回符合标签、上架状态的商品
        /// </summary>
        /// <param name="tagId">商品</param>
        /// <param name="state"></param>
        /// <param name="productsId"></param>
        /// <returns></returns>
        private IEnumerable<GetProductDto> GetProductByTagAndState(long tagId, int state)
        {
            return tagId == -1 ?
                //全部标签，包括没有标签的商品
                commodityDbContext.Products
                .Where(o => state == -1 ? true : o.State == state)
                .Select(o => new GetProductDto
                {
                    Id = o.Id,
                    ItemNumber = o.ItemNumber,
                    Name = o.Name,
                    Price = o.Price,
                    State = o.State,
                    CreateAt = o.CreateAt,
                    UpdateAt = o.UpdateAt
                })
                //特定标签的商品
                : commodityDbContext.Products
                .Join(commodityDbContext.ProductTags, o => o.Id, t => t.ProductId, (o, t) => new
                {
                    o.Id,
                    o.ItemNumber,
                    o.Name,
                    o.Price,
                    o.State,
                    o.CreateAt,
                    o.UpdateAt,
                    t.TagId
                })
                .Where(o => o.Id == tagId && state == -1 ? true : o.State == state)
                .Select(o => new GetProductDto
                {
                    Id = o.Id,
                    ItemNumber = o.ItemNumber,
                    Name = o.Name,
                    Price = o.Price,
                    State = o.State,
                    CreateAt = o.CreateAt,
                    UpdateAt = o.UpdateAt
                });
        }

        /// <summary>
        /// 根据筛选条件返回结果
        /// </summary>
        /// <param name="tagid">所选的标签，-1为全部</param>
        /// <param name="state">上架状态，-1为全部</param>
        /// <param name="search">搜索框的内容</param>
        /// <returns></returns>
        public ResponseResult<List<GetProductDto>> GetProducts(int tagId, int state, string search,int index)
        {
            //传入数据的校验
            if(state<-1||state>2)
            {
                return new ResponseResult<List<GetProductDto>>()
                {
                    State = 2,
                    Data = new List<GetProductDto>(),
                    Message = "状态传入错误"
                };
            }
            if(tagId!=-1&&commodityDbContext.Tags.Where(o=>o.Id==tagId).FirstOrDefault()==null)
            {
                return new ResponseResult<List<GetProductDto>>()
                {
                    State = 2,
                    Data = new List<GetProductDto>(),
                    Message = "对应标签不存在"
                };
            }
            //若search为null，返回所有符合的结果
            if (search == null) return new ResponseResult<List<GetProductDto>>()
            {
                State = 1,
                Data = GetProductByTagAndState(tagId, state).Distinct().OrderByDescending(o => o.UpdateAt).Skip((index - 1) * Page.pageSize).Take(Page.pageSize).ToList(),
                Message = "查询成功"
            };
            else return new ResponseResult<List<GetProductDto>>()
            {
                State = 1,
                Data = GetProductByTagAndState(tagId, state)
                    .Where(o => o.ItemNumber == search          //按商品编号查询
                             || o.Name.IndexOf(search) >= 0     //按商品名称查询
                             || PinYin.ConvertCh(o.Name).ToLower().IndexOf(String.Join("", search.Split(' ')).ToLower()) >= 0)//按拼音查询
                    .Distinct().OrderByDescending(o => o.UpdateAt).Skip((index - 1) * Page.pageSize).Take(Page.pageSize).ToList(),
                Message = "查询成功"
            };


        }
        /// <summary>
        /// 上架商品
        /// </summary>
        /// <param name="producsId">需要修改为下架的商品的id的列表</param>
        /// <returns></returns>
        public ResponseResult<bool> PutOnProducts(List<long>productsId)
        {
            var products = commodityDbContext.Products.Where(o=> productsId.Contains(o.Id)).ToList();
            if (products.Count != productsId.Count)
                return new ResponseResult<bool>()
                {
                    State = 3,
                    Data = false,
                    Message = "对应的商品不存在"
                };
            foreach (var product in products)
            {
                //已上架的商品不能上架
                if (product.State == 1)
                    return new ResponseResult<bool>()
                    {
                        State = 2,
                        Data = false,
                        Message = "已上架的商品不能上架"
                    };
            }
            foreach(var product in products)
            {
                product.State = 1;
            }

            var changes = commodityDbContext.SaveChanges() > 0;

            return new ResponseResult<bool>()
            {
                State = changes ? 1 : 3,
                Message = changes ? "上架成功" : "上架失败",
                Data = changes
            };
        }
        /// <summary>
        /// 下架商品
        /// </summary>
        /// <param name="productsId">要下架商品的id列表</param>
        /// <returns></returns>
        public ResponseResult<bool> PullOffProducts(List<long>productsId)
        {
            var products = commodityDbContext.Products.Where(o => productsId.Contains(o.Id)).ToList();
            if (products.Count != productsId.Count)
                return new ResponseResult<bool>()
                {
                    State = 3,
                    Data = false,
                    Message = "对应的商品不存在"
                };
            foreach (var product in products)
            {
                //只有已上架的商品才能下架
                if (product.State != 1)
                    return new ResponseResult<bool>()
                    {
                        State = 2,
                        Data = false,
                        Message = "只有已上架的商品才能下架"
                    };
            }
            foreach(var product in products)
            {
                product.State = 2;
            }
            var changes = commodityDbContext.SaveChanges() > 0;
            return new ResponseResult<bool>()
            {
                State = changes ? 1 : 3,
                Message = changes ? "下架成功" : "下架失败",
                Data = changes
            };
        }
        /// <summary>
        /// 获取商品的详细信息
        /// </summary>
        /// <param name="id">要获取的商品详细信息的id</param>
        /// <returns></returns>
        public ResponseResult<ProductDetailDto> GetProductDetail(long id)
        {
            var entity = commodityDbContext.Products.Where(o => o.Id == id).Select(o => new ProductDetailDto
            {
                ItemNumber = o.ItemNumber,
                Name = o.Name,
                Price = o.Price,
                Description = o.Description,
                State = o.State,
                CreateAt = o.CreateAt,
                UpdateAt = o.UpdateAt
            }).FirstOrDefault();
            if (entity == null)
                return new ResponseResult<ProductDetailDto>()
                {
                    State = 3,
                    Data = null,
                    Message = "对应的商品不存在"
                };
            return new ResponseResult<ProductDetailDto>()
            {
                State = 1,
                Data = entity,
                Message = "详情获取成功"
            };
        }
    }
}
